package com.yao.spider.proxy;


import com.yao.spider.core.httpclient.AbstractHttpClient;
import com.yao.spider.core.util.Config;
import com.yao.spider.core.util.Constants;
import com.yao.spider.core.util.SimpleThreadPoolExecutor;
import com.yao.spider.core.util.ThreadPoolMonitor;
import com.yao.spider.proxy.entity.Proxy;
import com.yao.spider.proxy.task.ProxyPageTask;
import com.yao.spider.proxy.task.ProxySerializeTask;
import com.yao.spider.core.util.HttpClientUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * Created by 单耀 on 2017/12/4.
 */
public class ProxyHttpClient extends AbstractHttpClient{
    private static final Logger logger = LoggerFactory.getLogger(ProxyHttpClient.class);
    //是否继续下载代理
    public static volatile boolean isContinue = true;
    private volatile static ProxyHttpClient instance;

    //单利模式获取实例方法
    public static ProxyHttpClient getInstance(){
        if (instance == null) {
            //加锁同步
            synchronized (ProxyHttpClient.class) {
                //双重检查锁 http://blog.csdn.net/chenchaofuck1/article/details/51702129
                if (instance == null) {
                    instance = new ProxyHttpClient();
                }
            }
        }
        return instance;
    }

    //代理ce'shi线程池
    private ThreadPoolExecutor proxyTestThreadExector;

    //从代理网站下载proxy，线程池
    private ThreadPoolExecutor proxyDownloadThreadExector;

    //TODO
    public ProxyHttpClient() {
        initThreadPool();

    }

    //TODO
    private void initThreadPool() {

        //TODO

        proxyTestThreadExector = new SimpleThreadPoolExecutor(100,100,0L,TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10000),
                "proxyTestThreadExecutor");
        //监控线程池情况
        proxyDownloadThreadExector = new SimpleThreadPoolExecutor(10,10,0L, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(),
                new ThreadPoolExecutor.DiscardPolicy(),
                "proxyDownloadThreadExecutor");
        new Thread(new ThreadPoolMonitor(proxyDownloadThreadExector,"proxyDownloadThreadExecutor")).start();
        new Thread(new ThreadPoolMonitor(proxyTestThreadExector,"proxyTestThreadExecutor")).start();
    }

     /**
     * 初始化proxy
     * 从本地文件中获取proxy地址
     *
     */
    private void initProxy(){
        Proxy[] proxyArray = null;
        try {
            proxyArray = (Proxy[]) HttpClientUtil.deserializeObject(Config.proxyPath);
            int usableProxyCount = 0;
            for (Proxy p : proxyArray){
                if (p == null){
                    continue;
                }
                p.setTimeIntervsl(Constants.TIME_INTERVAL);
                p.setFailureTimes(0);
                p.setSuccessfulTimes(0);
                long nowTime = System.currentTimeMillis();
                if (nowTime - p.getLastSuccessfulTime() < 1000 * 60 * 60){
                    //上次成功离现在少于一小时
                    ProxyPool.proxyQueue.add(p);
                    ProxyPool.proxySet.add(p);
                    usableProxyCount++;
                }
            }
            logger.info("反序列化proxy成功，" + proxyArray.length + "个代理,可用代理" + usableProxyCount + "个");
        } catch (Exception e) {
            logger.warn("反序列化proxy失败");
        }
    }
    /**
     * 从网页上下载代理
     */
    public void startGetProxy(){
        new Thread(new Runnable() {
            public void run() {
                while(isContinue) {
                    for (String url : ProxyPool.proxyMap.keySet()) {
                        //首次本机直接下载
                        proxyDownloadThreadExector.execute(new ProxyPageTask(url, false));
                       // new Thread(new PrintProxyPoolInfo()).start();
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            logger.error(e.getMessage(),e);
                        }
                    }
                    try {
                        Thread.sleep(1000*60*60);
                    } catch (InterruptedException e) {
                        logger.error(e.getMessage(),e);
//                        e.printStackTrace();
                    }
                }
            }
        }).start();
        new Thread(new ProxySerializeTask()).start();
    }


    public ThreadPoolExecutor getProxyDownLoadThreadExecutor() {
        return proxyDownloadThreadExector;
    }

    public ThreadPoolExecutor getProxyTestThreadExector() {
        return proxyTestThreadExector;
    }

    public static void main(String[] args) {
        ProxyHttpClient.getInstance().startGetProxy();
    }
}
